import {Code, CodeError, Http, HttpBuilder} from "mvx-foundation";
import RequestSuccessCallbackResult = UniNamespace.RequestSuccessCallbackResult;

const request = async (options: UniNamespace.RequestOptions):Promise<[RequestSuccessCallbackResult|undefined, Error|null]> => {
  return new Promise(resolve => {
    options.success = (result) => {
      resolve([result, null])
    };

    options.fail = (err) => {
      resolve([undefined, new Error(err.errMsg)])
    };
    uni.request(options)
  })
};

export class WXHttp implements Http {
  async send(): Promise<[string, CodeError]> {
    let headers:Record<string, string> = {};
    this.builder.headers().forEach(((value, key) => {
      headers[key] = value;
    }));


    const url = this.builder.getUrl();
    console.log(`${url} req `, this.builder.content());
    if (this.enableRealtimeLog) {
      uni.getRealtimeLogManager().info([`${url} req `, this.builder.content()]);
    }


    const [response, err] = await request({
      url:url,
      method:<any>this.builder.method(),
      header:headers,
      data:this.builder.content(),
      dataType:"其他",
      responseType:"text",
    });
    if (err) {
      return["", new CodeError(err.message, Code.ElseError)];
    }

    console.log(`${url} res `, response);

    if (this.enableRealtimeLog) {
      uni.getRealtimeLogManager().info([`${url} res `, response]);
    }

    const codeMapper:Map<string, number> = new Map<string, number>([
      ["1011", Code.TokenExpire],
      ["0010", Code.TokenExpire],
      ["0011", Code.TokenExpire],
      ["1010", Code.TokenExpire],
      ["0000", Code.Success],
    ]);

    try {
      const body:{code:string, message:string, status:boolean} = JSON.parse(<string>response?.data ?? JSON.stringify({}));
      if (codeMapper.has(body.code)) {
        return [<string>response?.data, new CodeError(body.message, codeMapper.get(body.code)!)];
      }

      if (response?.statusCode === Code.TokenExpire) {
        return [<string>response?.data ?? JSON.stringify({}), new CodeError(`${body.message}`, Code.TokenExpire)];
      }

      if (response?.statusCode === Code.Success && body.status) {
        return [<string>response?.data ?? JSON.stringify({}), new CodeError(`${body.message}`, Code.Success)];
      }

      return [<string>response?.data ?? JSON.stringify({}), new CodeError(`${body.message}`, Code.ElseError)];
    } catch (err) {
      const errMapper:Map<number, string> = new Map<number, string>([
        [504, "504 Gateway Time-out"]
      ]);
      if (errMapper.has(response!.statusCode)) {
        return [JSON.stringify({}), new CodeError(errMapper.get(response!.statusCode)!, Code.ElseError)];
      }

      return [JSON.stringify({}), new CodeError(`server error, code=${response!.statusCode}`, Code.ElseError)];
    }
  }

  constructor(private builder: HttpBuilder,  private enableRealtimeLog = false) { }
}